#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import uuid
import time

from common.common_models import LogDetail
from common.const import DBLogLevel
from dws.backup.cluster_backup import ClusterBackup
from dws.commons.common import log, select_available_port
from dws.commons.const import BackupResType, IntrusiveMode, DwsRoachPort
from dws.commons.function_tool import log_start
from dws.commons.dws_exception import ErrCodeException
from dws.commons.error_code import DwsErrorCode
from dws.commons.job_info import JobInfo
from dws.database.db_models import DwsIndex
from dws.resource.dws_database import DwsDatabase


class DataBaseBackup(ClusterBackup):

    def __init__(self, pid):
        super().__init__(pid)

    def construct_cmd(self, job_info: JobInfo, intrusive_mode, port):
        db_name = job_info.res_name
        log.info(f"Database, db_name: {db_name}, {job_info.log_format()}")

        if not DwsDatabase(job_info.usr, job_info.env_path).is_db_exists(db_name):
            log.error(f"Database [{db_name}] not exists, {job_info.log_format()}.")
            raise ErrCodeException(
                log_detail=LogDetail(
                    logDetail=DwsErrorCode.DATABASE_NOT_EXISTS,
                    logDetailParam=[db_name],
                    logTimestamp=int(time.time()),
                    logLevel=DBLogLevel.ERROR))

        master_port = select_available_port(DwsRoachPort.ROACH_PORT_START, DwsRoachPort.ROACH_PORT_END)
        if not master_port:
            raise Exception(f"Master port {master_port} can not use")
        agent_port = select_available_port(master_port + 1, DwsRoachPort.ROACH_PORT_END)
        if not agent_port:
            raise Exception(f"Agent port {agent_port} can not use")
        backup_cmd = f"python3 $GPHOME/script/GaussRoach.py -t backup --master-port {master_port} "\
            f"--media-type NBU --media-destination nbu_policy --filesplit-size 256  --agent-port {agent_port} "\
            f"--parallel-process {self._process_count} --dbname {db_name} "\
            f"--metadata-destination {job_info.metadata_destination} "
        if intrusive_mode == IntrusiveMode.NON_INTRUSIVE_MODE:
            backup_cmd += f" --nbu-on-remote --nbu-media-list /home/{job_info.usr}/media_list_file.txt "\
                f"--client-port {port}"

        log.debug(f"backup_cmd : {backup_cmd}, {job_info.log_format()}.")
        return backup_cmd

    @log_start()
    def save_cluster_info_with_query(self, job_info: JobInfo):
        """
        功能描述：保存table，database等信息
        """
        cluster_uuid = str(uuid.uuid1())
        cluster_name = job_info.pro_obj.get('parentName')
        self._db.insert_record(DwsIndex(UUID=cluster_uuid,
                                        NAME=cluster_name,
                                        TYPE=BackupResType.CLUSTER.value,
                                        PARENT_PATH='/',
                                        PARENT_UUID=''))

        self.save_database_info_with_query(job_info, cluster_uuid, '/' + cluster_name)

    @log_start()
    def save_database_info_with_query(self, job_info: JobInfo, parent_uuid: str, parent_path: str):
        database_uuid = str(uuid.uuid1())
        db_name = job_info.res_name
        self._db.insert_record(DwsIndex(UUID=database_uuid,
                                        NAME=db_name,
                                        TYPE=BackupResType.DATABASE.value,
                                        PARENT_PATH=parent_path,
                                        PARENT_UUID=parent_uuid))
        self.save_schema_info_with_query(job_info, job_info.res_name, database_uuid, f'{parent_path}/{db_name}')
